package com.mx.recycleview.manager

import android.content.Context
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.mx.recycleview.utils.Log
import kotlin.math.min

/**
 * 解决横向列表布局item高度为wrap_content 时，RecycleView高度为0的问题！
 * RecycleView 高度自适应
 */
open class AutoHeightLayoutManager(context: Context, private val isDebug: Boolean = false) :
    LinearLayoutManager(context, RecyclerView.HORIZONTAL, false) {
    override fun onMeasure(
        recycler: RecyclerView.Recycler,
        state: RecyclerView.State,
        widthSpec: Int,
        heightSpec: Int
    ) {
        if (state.isPreLayout || state.itemCount <= 0) {
            super.onMeasure(recycler, state, widthSpec, heightSpec)
            return
        }
        if (itemCount <= 0 || state.isPreLayout) {
            super.onMeasure(recycler, state, widthSpec, heightSpec)
            return
        }
        // 1.取出RecycleView的Spec模式和宽高
        val groupWidthMode = View.MeasureSpec.getMode(widthSpec)
        val groupHeightMode = View.MeasureSpec.getMode(heightSpec)
        val groupWidthSize = View.MeasureSpec.getSize(widthSpec)
        val groupHeightSize = View.MeasureSpec.getSize(heightSpec)

        val first = recycler.getViewForPosition(0)
        addView(first)
        val lp = (first.layoutParams as RecyclerView.LayoutParams)
        // 3.根据父容器的宽度数据获取Child的宽度Spec，高度默认为无限制
        val c_w_spec = RecyclerView.LayoutManager.getChildMeasureSpec(
            groupWidthSize,
            groupWidthMode,
            0,
            lp.width,
            true
        )
        val c_h_spec = RecyclerView.LayoutManager.getChildMeasureSpec(
            groupWidthSize,
            groupHeightMode,
            0,
            lp.height,
            true
        )
        first.measure(c_w_spec, c_h_spec)

        val first_measured_width = getDecoratedMeasuredWidth(first)
        val first_measured_height = getDecoratedMeasuredHeight(first)
        removeAndRecycleView(first, recycler)

        // 计算宽度规则
        val widthSize = when (groupWidthMode) {
            View.MeasureSpec.EXACTLY -> {
                // 容器宽度已经写死
                groupWidthSize
            }
            View.MeasureSpec.AT_MOST -> {
                // 容器有最大限制，则取容器和第一个View宽度的最小值
                min(groupWidthSize, first_measured_width)
            }
            else -> {
                // 容器无限制，宽度直接=第一个view的宽度
                first_measured_width
            }
        }

        /**
         * 计算高度规则
         */
        val heightSize = when (groupHeightMode) {
            View.MeasureSpec.EXACTLY -> {
                groupHeightSize
            }
            View.MeasureSpec.AT_MOST -> {
                min(groupHeightSize, first_measured_height)
            }
            else -> {
                first_measured_height
            }
        }
        setMeasuredDimension(widthSize, heightSize)

        if (isDebug) {
            Log("groupWidthMode= $groupWidthMode")
            Log("groupHeightMode= $groupHeightMode")
            Log("groupWidthSize= $groupWidthSize")
            Log("groupHeightSize= $groupHeightSize")
            Log("childWidthSpec= $c_w_spec")
            Log("childHeightSpec= $c_h_spec")
            Log("first_measured_width= $first_measured_width")
            Log("first_measured_height= $first_measured_height")
            Log("RecycleView setMeasuredDimension($widthSize, $heightSize)")
        }
    }

    override fun isAutoMeasureEnabled(): Boolean {
        return true
    }
}